package com.hb.bussiness.service.impl;


import com.hb.bussiness.dao.ElasticsearchDao;
import com.hb.bussiness.dto.CommonResponse;
import com.hb.bussiness.service.ESSearchService;
import com.hb.common.constants.QueryFiledNameConstant;
import com.hb.common.constants.StringPoolConstant;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.SuggestionBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@Service
public class ESSearchServiceImpl implements ESSearchService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ESSearchServiceImpl.class);

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * elasticsearch Dao 组件
     */
    @Autowired
    private ElasticsearchDao elasticsearchDao;

    /**
     * index名
     */
//    @Value("${elasticsearch.smartFurnIndex}")
    private String smartFurnIndex;

    /**
     * index别名
     */
//    @Value("${elasticsearch.smartFurnIndexAlias}")
    private String smartFurnIndexAlias;

//    @Value(value = "classpath:/mapping/smartFurnIndex2.json")
    private Resource smartFurnIndexResource;

    /**
     * 初始化索引
     *
     * @throws IOException
     */
//    @PostConstruct
    public void init() throws IOException {
        // 查询索引是否存在
        boolean storeIndexExistFlag = elasticsearchDao.indexExistFlag(smartFurnIndex);
        if (!storeIndexExistFlag) {
            // 不存在
            Boolean created = elasticsearchDao.createIndex(smartFurnIndex, smartFurnIndexAlias, smartFurnIndexResource);
            LOGGER.info("create index {} ", created ? "success" : "fail");
        } else {
            LOGGER.info("index:{} already exist", smartFurnIndex);
        }

    }

    /**
     * 搜索自动补全
     * @param context
     * @return
     */
    @Override
    public CommonResponse searchSpuSuggest(String context) {
        SearchSourceBuilder sourceBuilder = this.buildSpuSuggestSource(context);

        // 查询请求
        SearchRequest searchRequest = new SearchRequest(smartFurnIndexAlias);
        searchRequest.source(sourceBuilder);
        try {
            LOGGER.info("ES请求参数：{}", searchRequest.source().toString());
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            Set<String> resultSet = this.buildSpuSuggestWithSuggestResult(searchResponse);
            return CommonResponse.success(resultSet);
        } catch (IOException e) {
            LOGGER.error("查询失败", e);
        }
        return CommonResponse.fail();
    }

    /**
     * 构造查询
     * @param context
     * @return
     */
    public SearchSourceBuilder buildSpuSuggestSource(String context) {
        // 查询资源构建器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 获取标题自动补全，只需要在结果中返标题字段就好了
        sourceBuilder.fetchSource(QueryFiledNameConstant.INFO_TITLE, null);

        // 搜索建议
        SuggestionBuilder<CompletionSuggestionBuilder> suggestionBuilder =
                SuggestBuilders.completionSuggestion(QueryFiledNameConstant.INFO_TITLE +
                        StringPoolConstant.DOT + QueryFiledNameConstant.SUGGEST).prefix(context);
        //返回个数
        suggestionBuilder.size(QueryFiledNameConstant.SIZE);

        // 搜索建议构建器
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion(QueryFiledNameConstant.INFO_TITLE_SUGGEST_NAME, suggestionBuilder);

        sourceBuilder.suggest(suggestBuilder);
        return sourceBuilder;
    }

    /**
     * 构建搜索自动补全结果集
     *
     * @param searchResponse es搜索结果
     * @return 结果
     */
    private Set<String> buildSpuSuggestWithSuggestResult(SearchResponse searchResponse) {
        Set<String> resultSet = new LinkedHashSet<>();
        // 获取搜索建议结果
        CompletionSuggestion suggestion = searchResponse.getSuggest().getSuggestion(QueryFiledNameConstant.INFO_TITLE_SUGGEST_NAME);
        List<CompletionSuggestion.Entry> entries = suggestion.getEntries();
        for (CompletionSuggestion.Entry entry : entries) {
            for (CompletionSuggestion.Entry.Option option : entry.getOptions()) {
                resultSet.add(option.getText().toString());
            }
        }
        return resultSet;
    }
}
